
package cn.starrysky108.simpleerp.core.util;

import cn.starrysky108.simpleerp.core.properties.SimpleErpProperties;
import com.fasterxml.jackson.annotation.JsonValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis 工具类
 *
 * @author Carl Lee
 */
@Component
public class RedisUtil {

    private static RedisTemplate<String, Object> redisTemplate;
    private static long expire;

    @Autowired
    RedisUtil(RedisTemplate<String, Object> redisTemplate, SimpleErpProperties properties) {
        RedisUtil.redisTemplate = redisTemplate;
        RedisUtil.expire = properties.getCacheExpireTime();
    }

    /**
     * 获取 RedisTemplate 实例
     */
    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    /**
     * 判断key是否存在
     */
    public static Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 判断key集合中是否存在value
     */
    public Boolean hasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 删除key
     */
    public static Long del(String... key) {
        return redisTemplate.delete(Arrays.asList(key));
    }

    /**
     * 删除key集合中的所有value
     */
    public static Long sDel(String key, Object... value) {

        return redisTemplate.opsForSet().remove(key, value);
    }

    /**
     * 删除key hash集合中的hashKey
     */
    public static Long hDel(String key, Object... hashKey) {

        return redisTemplate.opsForHash().delete(key, hashKey);
    }

    /**
     * 读取String类型key中的数据
     * 对于复杂类型，redis默认返回的是LinkedHashMap,许要注意进行类型转换
     */
    public static Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 读取String类型key中的数据
     * 对于复杂类型，redis默认返回的是LinkedHashMap
     */
    public static <T> T get(String key, Class<T> clazz) {
        Object obj = get(key);
        if (ObjectUtils.isEmpty(obj)) {
            return null;
        }
        return CastUtil.objToAny(obj, clazz);
    }

    /**
     * 读取hash数据,指定值类型
     */
    public static <HV> Map<String, HV> hGet(String key, Class<HV> clazz) {
        Map<Object, Object> map = redisTemplate.opsForHash().entries(key);

        return CastUtil.castMap(map, String.class, clazz);
    }

    /**
     * 读取hash中hashKey的数据
     */
    public static Object hGet(String key, Object hashKey) {

        return key == null ? null : redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 存入String
     */
    public static void add(String key, Object value) {
        redisTemplate.opsForValue().set(key, value,expire,TimeUnit.DAYS);

    }

    /**
     * 存入String，过期时间
     */
    public static void add(String key, Object value, Long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);

    }

    /**
     * 存入未过期的token，带过期时间
     */
    public static void addToken(String prefix, String token) {
        long timeout = JwtUtil.getExpire(token);
        if (timeout > 0) {
            Long value = JwtUtil.getUserId(token);
            redisTemplate.opsForValue().set(prefix + token, value, timeout, TimeUnit.MILLISECONDS);
        }

    }

    /**
     * 存入Set
     */
    public static void sAdd(String key, Object... value) {
        redisTemplate.opsForSet().add(key, value,expire,TimeUnit.DAYS);
    }

    /**
     * 存入Hash
     */
    public static void hAdd(String key, Object hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 获取集合中的所有成员
     */
    public static Set<Object> sGet(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 设置过期时间
     */
    public Boolean expire(String key, long timeout, TimeUnit unit) {
        if (null == key || null == unit) {
            return false;
        }
        return redisTemplate.expire(key, timeout, unit);
    }
}

